package bibliotheque.nameserver.parser;

import bibliotheque.*;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.taskdefs.Exit;
import org.jdom.*;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

/**
 * Permet de parser un fichier XML definissant la topologie d'un reseau d'agences pour le service bibliotheque.
 * Le resultat du parsage est stocke dans une hashtable de type appropriee fournie par l'appelant du parsage.
 * Cette classe est appelée à etre modifier pour qu'elle devienne generique.
 * @author guillaume
 *
 */
public abstract class ParserNameServer {
    
    /**
     * Parse le fichier XML qui décrit la topologie du réseau d'agences
     * @param _FilePath : chemin du document XML à traiter.
     * @param neighbours : hashtable de la topologie du reseau d'agences.
     */
    public static Hashtable<String, ArrayList<String>> GetNeighbours(File _FilePath, String service) throws JDOMException,IOException {
        
        Hashtable<String, ArrayList<String>> neighbours = new Hashtable<String, ArrayList<String>>();
        
        SAXBuilder sxb = new SAXBuilder();
        Document document = sxb.build(_FilePath);

        
        /*########################*/
        /* Demmarage de l'analyse */
        /*########################*/
        
        
        /* On initialise un nouvel élément avec l'élément racine du document. */
        Element racine = document.getRootElement();
        
        /* On déclare le chemin à chercher. Ici, on souhaite chercher des "<service>" */
        XPath xpa = XPath.newInstance("//service");
        
            /* On applique cette recherche sur le noeud "racine", c'est le noeud "<config>".
             * On obtient tous les noeuds correspondant à notre recherche */
        List results = xpa.selectNodes(racine);
        //System.out.println("premiere liste : " + results.size());
        Iterator iterService = results.iterator() ;
        
        
        /*################################*/
        /* Parcour pour tous les services */
        /*################################*/
        
        //
        // variables
        //
        
        Element noeudCourant = null; // noeudCourant sur lequel est positionné le parser
        List resultsServeurs = null; // liste resultat des serveurs du service voulu.
        
        while (iterService.hasNext()){            /* tant qu'il y a des services dans l'annuaire */
            
            
            //System.out.println("il y a des services dans l'annuaire");
            
            /* on se positionne sur le noeud <service> */
            noeudCourant = (Element) iterService.next();
            //System.out.println("noeud courant premiere iteration : " + noeudCourant.getName());
            
                /* On récupère le nom du service. le "." en début du chemin : on part de la position courante
                 * le "@" indique que l'on cherche un attribut */
            xpa = XPath.newInstance("./@nom");
            
            //System.out.println("premier nom de service : " + xpa.valueOf(noeudCourant));
            
            
            /*##################################*/
            /* Si le service est "bibliotheque" */
            /*##################################*/
            if (xpa.valueOf(noeudCourant).compareTo(service) == 0) {
                
                //
                // Variables
                //
                
                ArrayList<String> voisins = null ; 	// Liste des adresses ip voisines pour un serveur donné
                String adresseip = null;			// Adresse ip du serveur analysé
                
                //System.out.println("nombre de sous noeud : " + noeudCourant.getChildren().size());
                //System.out.println("" + noeudCourant.getDescendants().);
                
                /* On declare la recherche de tous les serveurs */
                xpa = XPath.newInstance("//serveur");
                
                //System.out.println("xpa debug : " + xpa.selectNodes(noeudCourant).size());
                /* On applique cette recherche sur le noeud courant, ici <service nom="bibliotheque"> */
                resultsServeurs = xpa.selectNodes(noeudCourant);
                //System.out.println("noeud courant : " + noeudCourant.getName());
                //System.out.println("seconde liste : " + resultsServeurs.toString());
                Iterator iterServeur = resultsServeurs.iterator();
                
                
                
                /*##############################*/
                /* Parcour de tous les serveurs */
                /*##############################*/
                
                while (iterServeur.hasNext()){ /* Tant qu'il y a des serveurs pour le service */
                    
                    voisins = new ArrayList<String>();
                    //System.out.println("des serveurs sont présents");
                    
                    /* On positionne le noeudCourant sur le serveur a analyser */
                    noeudCourant = (Element) iterServeur.next();
                    
                    /* On recherche l'adresse ip du serveur */
                    xpa = XPath.newInstance("./adresseip");
                    //System.out.println("noeud courant : " + noeudCourant.getName());
                    //System.out.println("adresse ip n° " + /*j+*/" = " + xpa.valueOf(noeudCourant).toString());
                    //System.out.println("nombre de voisins : " + (noeudCourant.getChildren().size() - 1));
                    
                    /* On recupere directement le resultat, on n'applique pas la recherche à un noeud*/
                    adresseip = xpa.valueOf(noeudCourant).toString();
                    
                    /* On recherche à present les noeuds <voisin>*/
                    xpa = XPath.newInstance("./voisin");
                    /* La recherche est appliquée au noeud <serveur> courant*/
                    List listvoisins = xpa.selectNodes(noeudCourant);
                    Iterator iterVoisins = listvoisins.iterator();
                    //System.out.println("iterateur des voisins : " + listvoisins.toString());
                    
                    
                    /*########################################*/
                    /* Parcour de tous les voisins du serveur */
                    /*########################################*/
                    
                    while(iterVoisins.hasNext()){ /* Tant qu'il ya des voisins au serveur */
                        
                        /* On positionne le noeud courant sur un voisin*/
                        noeudCourant = (Element) iterVoisins.next();
                        
                        /* On recupere la donnee identifiant le voisin, à savoir son adresse ip */
                        voisins.add(noeudCourant.getValue().toString());
                        
                    }// while(iterVoisins.hasNext())
                    
                    /* Ajout de l'entrée dans la hashtable qui resume la topologie du réseau */
                    neighbours.put(adresseip, voisins);
                    
                }//while (iterServeur.hasNext())
                
            }// if (xpa.valueOf(noeudCourant).compareTo("bibliotheque") == 0)
            
        }// while (iterService.hasNext())
        
        
        return (neighbours);
        
    }// Parse(File _FilePath, Hashtable<String, ArrayList<String>> neighbours)
    
    public static ArrayList<String> GetServiceList(File _FilePath) throws JDOMException,IOException {
        
        
        
        ArrayList<String> list = new ArrayList<String>() ;
        
        SAXBuilder sxb = new SAXBuilder();
        Document document = sxb.build(_FilePath);
        
        
        Element racine = document.getRootElement();
        
        XPath xpa = XPath.newInstance("//service");
        List<Element> results = xpa.selectNodes(racine);
        
        Iterator<Element> iter = results.iterator();
        
        Element noeudcourant = null;
        xpa = XPath.newInstance("./@nom");
        
        while (iter.hasNext()) {
            noeudcourant = iter.next();            
            list.add(xpa.valueOf(noeudcourant).toString());
        }
        
        return (list);
    }
    
    
}
